package com.jic.point.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.util.Md5Utils;
import com.jic.point.mapper.*;
import com.jic.point.model.entity.*;
import com.jic.point.model.vo.request.ConfPointCardApplyRequest;
import com.jic.point.model.vo.request.ConfPointCardBatchRequest;
import com.jic.point.model.vo.request.ConfPointCardRequest;
import com.jic.point.model.vo.request.QuantityRequest;
import com.jic.point.model.vo.response.ConfPointCardResponse;
import com.jic.point.utils.BeanUtil;
import com.jic.point.utils.CardUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.jic.point.constant.consist.ResponseCode;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jic.common.base.vo.PageResult;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.function.LongFunction;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.jic.point.exception.AppRuntimeException;
import com.jic.point.service.ConfPointCardService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import sun.security.provider.MD5;

/**
 * 接口实现类
 *
 * @author : tzc
 * @version : v1.0.0
 * @email :
 * @since : 2020-03-09 10:12:20
 */
@Service
@Slf4j
public class ConfPointCardServiceImpl implements ConfPointCardService {

    @Resource
    private ConfPointCardMapper mapper;


    @Resource
    private ConfPointCardLogMapper confPointCardLogMapper;


    @Resource
    private ConfBdMapper confBdMapper;

    @Resource
    private ConfPointCardBatchMapper confPointCardBatchMapper;

    @Resource
    private ConfPlatformMapper confPlatformMapper;

    @Resource
    private ConfPointCardBatchMapper batchMapper;


    /**
     * 新增记录
     *
     * @param request 需要保存的入参实体类
     * @return int 是否保存成功
     */
    @Override
    public int save(ConfPointCard request) {
        int flag = mapper.insert(request);
        if (flag == 1) {
            return 1;
        } else {
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "新增失败");
        }
    }


    /**
     * 保存或修改记录信息
     *
     * @param requests 需要保存的入参实体类
     * @return int 是否保存或修改成功
     * author tzc
     * @date 2020-3-11 20:54:09
     * <p>
     * ConfPointCard confPointCard = new ConfPointCard();
     * BeanUtils.copyProperties(request, confPointCard);
     * confPointCard.setCreator(request.getAdminOperate().getOperator());
     * confPointCard.setCreatorName(request.getAdminOperate().getOperateName());
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveOrUpdate(ConfPointCardRequest requests) {
        log.info("保存或修改记录信息，入参 = {}", JSONObject.toJSONString(requests));
        try {
            if (requests == null) {
                throw new AppRuntimeException(ResponseCode.EXCEPTION, "入参为空");
            }
            ConfPointCard confPointCard = new ConfPointCard();
            BeanUtils.copyProperties(requests, confPointCard);
            if (requests.getId() != null) {
                confPointCard.setUpdater(requests.getAdminOperate().getOperator());
                confPointCard.setUpdaterName(requests.getAdminOperate().getOperateName());
                log.info("保存或修改记录信息，修改，入参 = {}", JSONObject.toJSONString(confPointCard));
                int flag = mapper.updateByPrimaryKey(confPointCard);
                if (flag == 1) {
                    return 1;
                }
            } else {
                confPointCard.setCreatorName(requests.getAdminOperate().getOperateName());
                confPointCard.setCreator(requests.getAdminOperate().getOperator());
                confPointCard.setCardNo(CardUtils.random("CONF_POINT_CARD", 1).get(0));
                log.info("保存或修改记录信息，保存，入参 = {}", JSONObject.toJSONString(confPointCard));
                int flag = mapper.insertSelective(confPointCard);


                if (flag == 1) {
//                    ConfPlatform confPlatform = new ConfPlatform();
//                    confPlatform.setCode(confPointCard.getFirstDemandSideCode());
//                    confPlatform.setAvailable(confPointCard.getTotal().subtract(confPointCard.getFrozen()));
//                    confPlatformMapper.updatePoint(confPlatform);
                    ConfPointCardLog confPointCardLog = new ConfPointCardLog();
                    confPointCardLog.setCardNo(CardUtils.random("CONF_POINT_CARD", 1).get(0));
                    confPointCardLog.setBdCode(requests.getSecondDemandSideCode());
                    confPointCardLog.setPlatformCode(requests.getFirstDemandSideCode());
                    confPointCardLog.setDeliveryType(1);
                    confPointCardLog.setType(1);
                    confPointCardLog.setDescription("手动添加积分卡");
                    confPointCardLog.setCreateTime(new Date());
                    confPointCardLog.setCreator(requests.getAdminOperate().getOperator());
                    confPointCardLog.setDeleteFlag(0);
                    confPointCardLog.setPointType(1L);
                    confPointCardLog.setAmount(BigDecimal.valueOf(1));
                    confPointCardLogMapper.insertSelective(confPointCardLog);
                    return 1;
                } else {
                    throw new AppRuntimeException(ResponseCode.EXCEPTION, "修改失败");
                }
            }
        } catch (Exception e) {
            log.error("用户保存或修改失败", e);
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "用户保存或修改失败");
        }
        return -1;
    }

    /**
     * 删除记录
     *
     * @param request 需要删除,含有主键的入参实体类
     * @return int 是否删除成功
     */
    @Override
    public int deleteByPrimaryKey(ConfPointCard request) {
        int flag = mapper.deleteByPrimaryKey(request);
        if (flag == 1) {
            return 1;
        } else {
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "删除失败");
        }
    }


    /**
     * 逻辑删除记录
     *
     * @param request 含有主键的逻辑删除实体类
     * @return int 是否逻辑删除成功
     */
    @Override
    public int deleteByPrimaryKeyLogically(ConfPointCard request) {
        request.setDeleteFlag(1);
        int flag = mapper.updateByPrimaryKey(request);
        if (flag == 1) {
            return 1;
        } else {
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "逻辑删除记录失败");
        }
    }


    /**
     * 修改
     *
     * @param request
     * @return
     */
    @Override
    public int updateByPrimaryKeySelective(ConfPointCard request) {
        try {
            log.info("修改记录");
            ConfPointCard param = new ConfPointCard();
            BeanUtils.copyProperties(request, param);
            int flag = mapper.updateByPrimaryKeySelective(param);
            if (flag == 1) {
                return 1;
            } else {
                throw new AppRuntimeException(ResponseCode.EXCEPTION, "修改记录失败");
            }
        } catch (Exception e) {
            log.error("修改记录失败", e);
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "修改记录失败");
        }

    }

    /**
     * 记录详情
     *
     * @param request 查询的入参实体类
     * @return 数据库查询到的实体类
     */
    @Override
    public ConfPointCard getByPrimaryKey(ConfPointCard request) {
        return mapper.selectByPrimaryKey(request);
    }


    /**
     * 分页查询
     *
     * @param request 分页查询入参实体类
     * @return 含有分页信息的实体类列表
     */
    @Override
    public PageInfo<ConfPointCard> listPageBySelective(ConfPointCard request, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        PageHelper.orderBy(" create_time desc");
        List<ConfPointCard> list = mapper.listPageBySelective(request);
        PageInfo pageInfo = new PageInfo(list);
        PageResult<ConfPointCard> result = new PageResult<>();
        result.setTotal(pageInfo.getTotal());
        result.setRows(list);
        return new PageInfo(list);
    }

    /**
     * 不分页查询
     *
     * @param request 不分页查询入参实体类
     * @return 数据库查到的实体类列表
     */
    @Override
    public List<ConfPointCard> listAllRecord(ConfPointCard request) {
        //分页处理
        request.setDeleteFlag(0);
        return mapper.selectBySelective(request);
    }

    /**
     * 批量生产卡号
     **/
    @Override
    @Transactional(rollbackFor = Exception.class) //回滚
    public Integer volumeProductionCardPoint(ConfPointCardBatchRequest requests) {
        log.error("生成积分卡开始,参数"+requests.toString());
        Integer result = 0;
        for (ConfPointCardBatchRequest request : requests.getList()) {
            List<QuantityRequest> quantity = new ArrayList<>();
            ConfPointCardBatch updateBatch = new ConfPointCardBatch();
            BigDecimal leftPointBatch = new BigDecimal(0); //获取生成积分卡的所有积分
            BigDecimal leftNumberBatch = new BigDecimal(0);//获取生成积分卡的所有数量


            for (QuantityRequest quantityRequest : request.getQuantity()) {
                if (quantityRequest.getTotalNum().compareTo(BigDecimal.ZERO)==0) continue;
                List<ConfPointCard> list = new ArrayList<>();
                BigDecimal num = quantityRequest.getTotalNum();
                //先判断积分是否足够
                //获取生成积分卡所需要的积分
                BigDecimal leftPoint = num.multiply(quantityRequest.getPointCardLimit());
                leftPointBatch=leftPointBatch.add(leftPoint);
                leftNumberBatch=leftNumberBatch.add(quantityRequest.getTotalNum());
                //判断生成积分卡的积分是否足够，不足够返回积分不住
                if (request.getLeftPoint().compareTo(leftPoint) == -1) {
                    log.error("批量生成积分卡","积分不足请充值积分在进行生成积分卡");
                    throw new AppRuntimeException("8888", "积分不足，请充值积分在进行生成积分卡");
                }
                String[] card = {"HX","DZ"};
                //生成卡号，并以卡号进行遍历添加
                List<String> random = CardUtils.random(card[(int)(request.getType()-1)],quantityRequest.getPointCardLimit(),Integer.parseInt(num.toString()));
                for (String cardNo : random) {
                    //添加积分卡
                    ConfPointCard batch = new ConfPointCard();
                    batch.setApplyCode(request.getCode());
                    batch.setFirstDemandSideCode(request.getFirstDemandCode());
                    batch.setSecondDemandSideCode(request.getSecondDemandCode());
                    batch.setCardType(request.getType());
                    batch.setCardNo(cardNo);
                    batch.setCardPassword("" + (int) (Math.random() * 900000 + 1000000));
                    batch.setApplyTime(request.getApplyTime());
                    batch.setTotal(quantityRequest.getPointCardLimit());
                    batch.setAvailable(quantityRequest.getPointCardLimit());
                    batch.setLimited(quantityRequest.getPointCardLimit());
                    batch.setExpiryTime(request.getExpiryTime());
                    batch.setCreator(requests.getAdminOperate().getOperator());
                    batch.setCreatorName(requests.getAdminOperate().getOperateName());
                    batch.setCardSort(request.getCardSort());
                    list.add(batch);
                }
                if (list!=null&&list.size()>0){
                    result += mapper.volumeProductionCardPoint(list);
                }
                if (result < 1) {
                    log.error("批量生成积分卡失败","积分卡生成的太多");
                    throw new AppRuntimeException("8888", "批量生成积分卡失败");
                }
                quantityRequest.setTotalNum(BigDecimal.ZERO);
                quantity.add(quantityRequest);
            }
            updateBatch.setQuantity(JSON.toJSON(quantity).toString());
            updateBatch.setId(request.getId());
            updateBatch.setLeftPoint(leftPointBatch);
            updateBatch.setLeftNum(leftNumberBatch);
            updateBatch.setSts(3L);
            Integer value = confPointCardBatchMapper.updateByPrimaryId(updateBatch);
            if (value==0){
                log.error("批量生成积分卡失败","积分卡剩余数量或者积分不足");
                throw new AppRuntimeException("8888", "积分卡剩余数量或者积分不足");
            }
        }
        log.error("生成积分卡结束,返回参数"+(result>0));
        return result;

    }

    /**
     *
     *
     * @description:  批量生成积分卡
     * @return:
     * @author: fengrui
     * @time: 2020/12/02 15:28
     */
    @Override
    @Transactional(rollbackFor = Exception.class) //回滚
    public ConfPointCardResponse generateIntegralCard(ConfPointCardBatchRequest request) {
        Integer result = 0;
        ConfPointCardBatch query = new ConfPointCardBatch();
        query.setCode(request.getCode());
        ConfPointCardBatch confPointCardBatch = batchMapper.selectByPrimaryCode(query);
        if (confPointCardBatch == null) {
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "生成失败，没有相应的编码");
        }
        if (!(confPointCardBatch.getLeftNum().compareTo(request.getGenerateNumber()) == 1 || confPointCardBatch.getLeftNum().compareTo(request.getGenerateNumber()) == 0)) {
            throw new AppRuntimeException("8888", "生成失败，数量不足");
        }
        List<ConfPointCard> list = new ArrayList<>();
        List<String> random = CardUtils.random("USER", Integer.valueOf(request.getGenerateNumber().toString()));
        for (String cardNo : random) {
            ConfPointCard batch = new ConfPointCard();
            batch.setApplyCode(confPointCardBatch.getCode());
            batch.setFirstDemandSideCode(confPointCardBatch.getCode());
            batch.setSecondDemandSideCode(confPointCardBatch.getSecondDemandCode());
            batch.setCardType(confPointCardBatch.getType());
            batch.setCardNo(cardNo);
            batch.setApplyCode(confPointCardBatch.getFirstDemandCode());
            batch.setTotal(confPointCardBatch.getPointCardLimit());
            batch.setAvailable(confPointCardBatch.getPointCardLimit());
            batch.setLimited(confPointCardBatch.getPointCardLimit());
            batch.setApplyTime(confPointCardBatch.getAuditTime());
            batch.setExpiryTime(confPointCardBatch.getExpiryTime());
            batch.setCreatorName(request.getAdminOperate().getOperateName());
            batch.setCreator(request.getAdminOperate().getOperator());
            batch.setSts(request.getSts());
            list.add(batch);
        }
        result += mapper.volumeProductionCardPoint(list);
        if (result > 0) {
            ConfPointCardBatch batch = new ConfPointCardBatch();
            if (confPointCardBatch.getLeftNum().compareTo(request.getGenerateNumber()) == -1) {
                throw new AppRuntimeException("8888", "生成失败，数量不足");
            }
            batch.setLeftNum(confPointCardBatch.getLeftNum().subtract(request.getGenerateNumber()));
            batch.setId(confPointCardBatch.getId());
            //修改批量生成积分卡表中的剩余数量
            confPointCardBatchMapper.updateByPrimaryKey(batch);
        } else {
            throw new AppRuntimeException(ResponseCode.EXCEPTION, "批量生成积分卡失败");
        }
        return null;
    }

    @Override
    public ConfPointCard activateCardPoint(ConfPointCard confPointCard) {
        return mapper.activateCardPoint(confPointCard);
    }

    @Override
    public List<ConfPointCardResponse> count() {
        List<ConfPointCard> list=mapper.count();
        List<ConfPointCardResponse> collect = list.stream().map(item -> {
            ConfPointCardResponse response = new ConfPointCardResponse();
            response.setTotal(item.getTotal());
            response.setSts(item.getSts());
            return response;
        }).collect(Collectors.toList());
        return collect;
    }
}
